package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;

public class BallGameJFrame extends JFrame {
    private static final int WIDTH = 800;// 区域大小
    private static final int HEIGHT = 800;// 区域大小
    private static final int DELAY = 1;// 定时器延迟时间 单位为毫秒
    private Ball playerBall;
    private ArrayList<Ball> balls;
    private int score;
    private JLabel scoreLabel;// 用来显示分数

    public BallGameJFrame() {
        setTitle("Ball Game");
        setSize(WIDTH, HEIGHT);
        // 获取屏幕尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;
        // 获取窗口尺寸
        int windowWidth = this.getWidth();
        int windowHeight = this.getHeight();
        // 计算窗口位置
        int xPos = (screenWidth - windowWidth) / 2;
        int yPos = (screenHeight - windowHeight) / 2;
        
        // 设置窗口位置
        this.setLocation(xPos, yPos);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        // 设置边框
        playerBall = new Ball(50, 50, 30, Color.blue);// 初始小球
        balls = new ArrayList<>();
        score = 0;

        addKeyListener(new KeyListener() {// 用来监视键盘
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyPressed(KeyEvent e) {
                handleKeyPress(e.getKeyCode());
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }
        });
        setFocusable(true);

        Timer timer = new Timer(DELAY, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                repaint();// 绘制
                updateBalls();// 小球随意移动
                checkCollision();// 监测碰撞
            }
        });
        timer.start();
        // 分数的块
        scoreLabel = new JLabel("Score: 0");
        scoreLabel.setFont(new Font("Arial", Font.BOLD, 24));
        scoreLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        scoreLabel.setVerticalAlignment(SwingConstants.TOP);
        scoreLabel.setBounds(WIDTH - 150, 20, 130, 30);
        add(scoreLabel);
    }

    private void handleKeyPress(int keyCode) {// 监测方向键 用来移动小球
        int step = 10;
        switch (keyCode) {
            case KeyEvent.VK_UP:
                playerBall.move(0, -step);
                break;
            case KeyEvent.VK_DOWN:
                playerBall.move(0, step);
                break;
            case KeyEvent.VK_LEFT:
                playerBall.move(-step, 0);
                break;
            case KeyEvent.VK_RIGHT:
                playerBall.move(step, 0);
                break;
        }
    }

    private void updateBalls() {// 实时更新移动小球的位置
        if (isVisible()) {
            for (Ball ball : balls) {
                ball.x += ball.disX;
                ball.y += ball.disY;
                // 如果超出范围 位移方向发生变化
                if (ball.x <= 0 || ball.x >= WIDTH - 30) {
                    ball.disX *= -1;
                }
                if (ball.y <= 0 || ball.y >= WIDTH - 30) {
                    ball.disY *= -1;
                }
            }
        }
    }

    public boolean contain(Ball a, Ball b) {// 判断a能不能吃掉b
        boolean flag=false;
        double dis=distance(a,b);
        int r1 = a.r;
        if (dis <= r1)
            flag = true;
        return flag;
    }

    private void checkCollision() {
        repaint();
        int cnt = 0;// 用来计数现在比玩家的球小的球有几个 如果比较少就生成一号球 反之生成二号球
        for (int i = 0; i < balls.size(); i++) {
            if (balls.get(i).r <= playerBall.r) {
                cnt++;
            }
        }
        for (int i = 0; i < balls.size(); i++) {
            Ball ball = balls.get(i);
            if (playerBall.intersects(ball)) {

                if (playerBall.r >= ball.r) {
                    if (contain(playerBall, ball)) {
                        // System.out.println("playerBall: "+playerBall.x+" "+playerBall.y+" "+playerBall.r+" "+"ball: "+ball.x+" "+ball.y+" "+ball.r);
                        playerBall.grow();
                        balls.remove(i);
                        i--;
                        if (cnt < 3)
                            spawnRandomBall1();
                        else
                            spawnRandomBall2();
                        score += ball.r;
                        scoreLabel.setText("Score: " + score);
                        if (score >= 30000) {
                            gameOver();
                        }
                    }
                } else {
                    if (contain(ball, playerBall)) {
                        // System.out.println("ball: "+ball.x+" "+ball.y+" "+ball.r+"playerBall: "+playerBall.x+" "+playerBall.y+" "+playerBall.r+" ");
                        gameOver();
                    }
                }
            }
        }
    }

    private void spawnRandomBall1() {// 生成一个比现在这个小的
        Random random = new Random();
        int x = random.nextInt(WIDTH - 50);
        int y = random.nextInt(HEIGHT - 50);
        int r = random.nextInt(playerBall.r-5) + 5;
        Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
        Ball ball = new Ball(x, y, r, color);
        balls.add(ball);
    }

    private void spawnRandomBall2() {// 随机生成一个
        Random random = new Random();
        int x = random.nextInt(WIDTH - 50);
        int y = random.nextInt(HEIGHT - 50);
        int r = random.nextInt(playerBall.getR() + 50) + 5;
        Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
        Ball ball = new Ball(x, y, r, color);
        balls.add(ball);
    }

    private void gameOver() {
        if (isVisible()) {// 只有当 BallGame 窗口是可见的时候才显示消息框
            BoardDao boardDao = new BoardDaoImpl();
            boardDao.insertBoard(SignIn.playerId, score);
            JOptionPane.showMessageDialog(this, "游戏结束!");
        }
        dispose();
        // System.exit(0);
    }

    public void paint(Graphics g) {
        Image offScreen = createImage(getWidth(), getHeight());
        Graphics offG = offScreen.getGraphics();
        // 绘制小球
        offG.setColor(getBackground());
        offG.fillRect(0, 0, getWidth(), getHeight());
        offG.setColor(Color.BLUE);
        offG.fillOval(playerBall.x,playerBall.y,playerBall.r*2,playerBall.r*2);
        for (Ball ball : balls) {
            offG.setColor(ball.color);
            offG.fillOval(ball.x,ball.y,ball.r*2,ball.r*2);
        }
        g.drawImage(offScreen, 0, 0, this);
    }


    public static void runGame() {
        SwingUtilities.invokeLater(() -> {
            BallGameJFrame ballGame = new BallGameJFrame();
            ((JComponent) ballGame.getContentPane()).setDoubleBuffered(true);
            ballGame.spawnRandomBall1();
            ballGame.spawnRandomBall1();
            ballGame.spawnRandomBall2();
            ballGame.spawnRandomBall2();
            ballGame.spawnRandomBall2();
            ballGame.setVisible(true);
        });
    }

    public static double distance(Ball a,Ball b){
        double dx=a.x+a.r-b.x-b.r,dy=a.y+a.r-b.y-b.r;
        double dis=Math.sqrt(dx*dx+dy*dy);
        return dis;
    }
    private class Ball {
        private int x;// 坐标
        private int y;// 坐标
        //坐标指的是左上角
        private int r;// 半径
        private int disX, disY;// 位移
        private Color color;

        public Ball(int x, int y, int r, Color color) {
            this.x = x;
            this.y = y;
            this.r = r;
            this.color = color;
            // this.disX=1;
            // this.disY=1;
            this.disX = (int) (Math.random() * 3) + 1;
            this.disY = (int) (Math.random() * 3) + 1;
        }

        public int getR() {
            return r;
        }

        public void move(int dx, int dy) {
            int tmpX = x + dx, tmpY = y + dy;
            if (tmpX > 0 && tmpX < WIDTH - 30) {
                x += dx;
            }
            if (tmpY > 0 && tmpY < HEIGHT - 30) {
                y += dy;
            }
        }

        public boolean intersects(Ball other) {
            double dis=distance(this,other);
            return dis < r + other.r;
        }

        public void grow() {
            r += 3;
        }
    }

    public static int max(int a, int b) {
        int res = 0;
        if (a > b)
            res = a;
        else
            res = b;
        return res;
    }
}
